{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "hMMdZ1vnxj8f"
   },
   "source": [
    "<center>\n",
    "    <p style=\"text-align:center\">\n",
    "        <img alt=\"phoenix logo\" src=\"https://storage.googleapis.com/arize-phoenix-assets/assets/phoenix-logo-light.svg\" width=\"200\"/>\n",
    "        <br>\n",
    "        <a href=\"https://arize.com/docs/phoenix/\">Docs</a>\n",
    "        |\n",
    "        <a href=\"https://github.com/Arize-ai/phoenix\">GitHub</a>\n",
    "        |\n",
    "        <a href=\"https://arize-ai.slack.com/join/shared_invite/zt-2w57bhem8-hq24MB6u7yE_ZF_ilOYSBw#/shared-invite/email\">Community</a>\n",
    "    </p>\n",
    "</center>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "se3M7GECJfpZ"
   },
   "source": [
    "# AutoGen Orchestrator Agent\n",
    "\n",
    "In this tutorial, we'll explore orchestrator agent workflows with [AutoGen GroupChats](https://microsoft.github.io/autogen/dev//user-guide/core-user-guide/design-patterns/group-chat.html).\n",
    "\n",
    "**Agent orchestration** enables collaboration among multiple specialized agents, activating only the most relevant one based on the current subtask context. Instead of relying on a fixed sequence, agents dynamically participate depending on the state of the conversation. At termination, results are synthesized together.\n",
    "\n",
    "Agent orchestrator workflows simplifies this routing pattern through a central orchestrator (`GroupChatManager`) that selectively delegates tasks to the appropriate agents. Each agent monitors the conversation but only contributes when their specific expertise is required. With Phoenix tracing, you get full visibility into the orchestration flow to see which agents engaged, when they were activated, and why.\n",
    "\n",
    "In this example, we'll build a smart trip planning assistant where subtasks like destination research, hotel booking, and activity suggestions are dynamically sent to the right specialized agent.\n",
    "\n",
    "By the end of this tutorial, you’ll learn how to:\n",
    "\n",
    "- Set up multiple specialized AutoGen agents in a `GroupChat`\n",
    "\n",
    "- Use a `GroupChatManager` to enable dynamic agent routing\n",
    "\n",
    "- Incorporate human feedback in your agent set up\n",
    "\n",
    "- Trace and visualize agent interactions using Phoenix\n",
    "\n",
    "⚠️ You'll need an OpenAI Key for this tutorial.\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "G2j6_RvFJfpa"
   },
   "source": [
    "## Set up Keys and Dependencies\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "!pip install -qq pyautogen==0.9 autogen-agentchat~=0.2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "!pip install -qqq arize-phoenix arize-phoenix-otel openinference-instrumentation-openai"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import os\n",
    "from getpass import getpass\n",
    "\n",
    "import autogen\n",
    "\n",
    "if \"OPENAI_API_KEY\" not in os.environ:\n",
    "    os.environ[\"OPENAI_API_KEY\"] = getpass(\"🔑 Enter your OpenAI API key: \")\n",
    "\n",
    "if \"PHOENIX_API_KEY\" not in os.environ:\n",
    "    os.environ[\"PHOENIX_API_KEY\"] = getpass(\"🔑 Enter your Phoenix API key: \")\n",
    "\n",
    "if \"PHOENIX_COLLECTOR_ENDPOINT\" not in os.environ:\n",
    "    os.environ[\"PHOENIX_COLLECTOR_ENDPOINT\"] = getpass(\"🔑 Enter your Phoenix Collector Endpoint\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "ibmucjY_QkaH"
   },
   "source": [
    "## Configure Tracing\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from phoenix.otel import register\n",
    "\n",
    "tracer_provider = register(\n",
    "    project_name=\"autogen-agents\",\n",
    "    auto_instrument=True,\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "kTVRWf0NJfpc"
   },
   "source": [
    "## Example Orchestrator Task: Travel Agent\n",
    "\n",
    "This example shows how to build a dynamic travel planning assistant. A `GroupChatManager` coordinates specialized agents to adapt to the user's evolving travel needs.\n",
    "\n",
    "**User Interaction**:\n",
    "A `UserProxyAgent` acts as the human user, configured with `human_input_mode=\"TERMINATE\" `and a custom `is_termination_msg` that ends the session when a message ends with TERMINATE.\n",
    "\n",
    "**Specialized Travel Agents**:\n",
    "Three AssistantAgents handle specific tasks.\n",
    "\n",
    "- Flight Planner — suggests flight options.\n",
    "\n",
    "- Hotel Finder — recommends accommodations.\n",
    "\n",
    "- Activity Suggester — proposes activities and attractions.\n",
    "\n",
    "**GroupChat Setup**:\n",
    "A GroupChat bundles the user and specialized agents, managing message flow with a maximum round limit (ex: 10 rounds).\n",
    "\n",
    "**Orchestrator**:\n",
    "The `GroupChatManager` oversees the conversation, routing tasks to the right agent based on context.\n",
    "\n",
    "![Diagram](https://storage.googleapis.com/arize-phoenix-assets/assets/images/autogen_orchestrator_diagram.png)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "qq5TvGKzO685"
   },
   "source": [
    "## Define Agent"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "dpjxM6BGLGW0"
   },
   "source": [
    "The `llm_config` specifies the configuration used for all the assistant agents.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "llm_config = {\n",
    "    \"model\": \"gpt-4o\",\n",
    "    \"api_key\": os.environ[\"OPENAI_API_KEY\"],\n",
    "}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Specialized LLM Agents\n",
    "flight_planner = autogen.AssistantAgent(\n",
    "    name=\"FlightPlanner\",\n",
    "    llm_config=llm_config,\n",
    "    system_message=\"You are a flight planning assistant. You help book flights and find the best travel routes. Focus on using freely accessible sources.\",\n",
    ")\n",
    "\n",
    "hotel_finder = autogen.AssistantAgent(\n",
    "    name=\"HotelFinder\",\n",
    "    llm_config=llm_config,\n",
    "    system_message=\"You are a hotel booking assistant. You help find the best accommodations. Focus on using freely accessible sources.\",\n",
    ")\n",
    "\n",
    "activity_suggester = autogen.AssistantAgent(\n",
    "    name=\"ActivitySuggester\",\n",
    "    llm_config=llm_config,\n",
    "    system_message=\"You are a travel activity expert. You suggest interesting activities and tours in a destination.\",\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "user_proxy = autogen.UserProxyAgent(\n",
    "    name=\"UserProxy\",\n",
    "    human_input_mode=\"TERMINATE\",\n",
    "    max_consecutive_auto_reply=5,\n",
    "    is_termination_msg=lambda x: x.get(\"content\", \"\").rstrip().endswith(\"TERMINATE\"),\n",
    "    code_execution_config={\n",
    "        \"work_dir\": \"coding\",\n",
    "        \"use_docker\": False,\n",
    "    },\n",
    "    system_message=\"A human user seeking travel planning assistance. Reply TERMINATE when the task is done.\",\n",
    ")\n",
    "\n",
    "agents = [user_proxy, flight_planner, hotel_finder, activity_suggester]\n",
    "\n",
    "group_chat = autogen.GroupChat(agents=agents, messages=[], max_round=10)\n",
    "\n",
    "manager = autogen.GroupChatManager(\n",
    "    groupchat=group_chat,\n",
    "    llm_config=llm_config,\n",
    "    system_message=\"\"\"\n",
    "    You are a coordinator managing a travel planning discussion between a user, a flight planner, a hotel finder, and an activity suggester.\n",
    "    Your goal is to ensure the user's request is fully addressed by coordinating the specialists.\n",
    "    Ensure each specialist contributes relevant information sequentially (e.g., flights first, then hotels, then activities, unless the user specifies otherwise).\n",
    "    Summarize the final plan. Be sure to reply TERMINATE when the plan is complete.\n",
    "    \"\"\",\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "TMH-RlkA_jEH"
   },
   "source": [
    "## Run Agent"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from opentelemetry.trace import StatusCode\n",
    "\n",
    "tracer = tracer_provider.get_tracer(__name__)\n",
    "with tracer.start_as_current_span(\n",
    "    \"TravelAgent\",\n",
    "    openinference_span_kind=\"agent\",\n",
    ") as agent_span:\n",
    "    agent_span.set_status(StatusCode.OK)\n",
    "    user_proxy.initiate_chat(\n",
    "        manager,\n",
    "        message=\"I want to plan a 5-day trip to Paris, France, sometime in October. I'm interested in museums and good food. Find flight options from SFO, suggest mid-range hotels near the city center, and recommend some relevant activities.\",\n",
    "    )"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "pwbMnN9EfGWF"
   },
   "source": [
    "## View Results in Phoenix"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "WyS3R8I1fv0u"
   },
   "source": [
    "When viewing the traces in Phoenix, you can see how the `GroupChatManager` delegated subtasks to specialized agents step-by-step. The trace shows the order in which each agent responded, making it easy to verify the flow from flight planning to hotel booking to activity suggestions.\n",
    "\n",
    "![Results](https://storage.googleapis.com/arize-phoenix-assets/assets/images/autogen_routing_results.png)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "5eDcTShcgRF5"
   },
   "source": [
    "Run the cell below to see full tracing results."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from IPython.display import HTML\n",
    "\n",
    "HTML(\"\"\"\n",
    "<video width=\"800\" height=\"600\" controls>\n",
    "  <source src=\"https://storage.googleapis.com/arize-phoenix-assets/assets/images/autogen_router_agent.mp4\" type=\"video/mp4\">\n",
    "  Your browser does not support the video tag.\n",
    "</video>\n",
    "\"\"\")"
   ]
  }
 ],
 "metadata": {
  "language_info": {
   "name": "python"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}
